/**
 * Framework for batch testing user profile models
 * Final project by Sergey Nepomnyachiy and Julia Polchin
 * Supervisor: Tsvi Kuflik
 *
 */
package core.XML;

import interfaces.GeneratorInterface;

import java.lang.reflect.Constructor;
import java.util.Vector;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import core.environment.Defines;
import core.environment.fVector;
import core.generators.DummyGen;

/**
 * @author Sergey and Julia
 * 
 */
public class CommonParsers {

	/**
	 * Parse XML chunk containing types and return Class[].
	 * 
	 * @param types
	 *            NodeList with types.
	 * @return Array of Class class objects of given types.
	 */
	public static Class<?>[] getParTypes(NodeList types) {
		Vector<Class<?>> argTypes = new Vector<Class<?>>();
		int type = 0;
		for (int i = 1; i < types.getLength(); i += 2) {
			if (types.item(i).getNodeName().equals(DefinesXML.XML_TYPE))
				argTypes.add(makeClass(types.item(i).getAttributes()
						.getNamedItem(DefinesXML.XML_NAME).getTextContent()));
		}

		Class<?> result[] = new Class[argTypes.size()];
		for (Class<?> c : argTypes) {
			result[type++] = c;
		}

		return result;

	}

	/**
	 * Creates Class class objects for different types
	 * 
	 * @param type
	 *            The name of the type
	 * @return Class class objects for the given type
	 */
	public static Class<?> makeClass(String type) {

		if (type.startsWith(DefinesXML.TYPE_STRING))
			return String.class;
		if (type.startsWith(DefinesXML.TYPE_INT))
			return Integer.class;
		if (type.startsWith(DefinesXML.TYPE_DOUBLE))
			return Double.class; 
		if (type.startsWith(DefinesXML.TYPE_VECTOR))
			return fVector.class;
		try {
			return Class.forName(type);
		} catch (ClassNotFoundException e) {
			Defines.printException("wrong typename " + type );
		}
		return null;
	}

	/**
	 * Creates a class using its name
	 * @param clssName name of the class
	 * @return constructed class object
	 */
	public static Class<?> getFacade(String clssName) {
		Thread t = Thread.currentThread();
		ClassLoader cl = t.getContextClassLoader();
		try {
			return cl.loadClass(clssName);
		} catch (ClassNotFoundException e) {
			Defines.printException(DefinesXML.BADXML_ERROR_STRING
					+ e.getMessage());
		}

		return null;
	}

	/**
	 * Getting constructor for class
	 * @param className the name of the class
	 * @param types types of arguments to this class
	 * @return constructor of this class
	 */
	public static Constructor<?> getCtor(String className, NodeList types) {
		Class<?> facade = getFacade(className);
		Class<?>[] args = getParTypes(types);
		Constructor<?> ctor = null;
		try {
			ctor = facade.getConstructor(args);
		} catch (SecurityException e) {
			Defines.printException(DefinesXML.BADXML_ERROR_STRING
					+ e.getMessage());
		} catch (NoSuchMethodException e) {
			Defines.printException(DefinesXML.BADXML_ERROR_STRING
					+ e.getMessage());
		}

		return ctor;
	}

	/**
	 * Parsing out generator
	 * @param gens XML with generator elements
	 * @return the first generator it succeeds in parsing
	 */
	@SuppressWarnings("boxing")
	public static GeneratorInterface<?> getGen(NodeList gens) {
		for (int i = 0; i < gens.getLength(); ++i) {
			Node n = gens.item(i);
			if (DefinesXML.GEN_TAG.equals(n.getNodeName()))
				return GeneratorsParser.parseGenerator(n, 0)[0];
		}
		return new DummyGen();
	}
}
